package com.wocai.jrt.orgadmin.employee.action;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Pattern;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.vteba.security.spi.cache.SecurityUserCache;
import com.vteba.security.user.IUserDetails;
import com.vteba.utils.common.PropUtils;
import com.vteba.utils.id.UUID;
import com.vteba.utils.id.UUIDUtils;
import com.vteba.web.action.GenericAction;
import com.vteba.web.action.JsonBean;
import com.vteba.web.editer.StringEditor;
import com.wocai.jrt.orgadmin.employee.bean.EmployeeDetailResBean;
import com.wocai.jrt.orgadmin.employee.bean.UserPasswordReqBean;
import com.wocai.jrt.orgadmin.employee.model.Employee;
import com.wocai.jrt.orgadmin.employee.model.EmployeeGroup;
import com.wocai.jrt.orgadmin.employee.service.spi.EmployeeGroupService;
import com.wocai.jrt.orgadmin.employee.service.spi.EmployeeService;
import com.wocai.jrt.orgadmin.utils.ImgType;
import com.wocai.jrt.orgadmin.utils.MyFileUtils;
import com.wocai.jrt.orgadmin.utils.SmsUtils;
import com.wocai.jrt.orgadmin.utils.UserUtils;

/**
 * 员工控制器
 * 
 * @author yinlei
 * @date 2015-8-4 15:49:29
 */
@Controller
@RequestMapping("/employee")
public class EmployeeAction extends GenericAction<Employee> {
	private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeAction.class);

	private static final Pattern IMAGE = Pattern.compile("^(.*)+.(jpg|jpeg|gif|png|bmp)$");
	// 这个对年没有限制，可以2020年以后，如3000，4000等
	private static final Pattern ID = Pattern
			.compile("^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[Xx])$)$");
	// 以1开头，除了没有10，其他都有
	private static final Pattern MOBILE = Pattern.compile("^(0|86|17951)?(1[123456789])[0-9]{9}$");

	private static final String AUTH_ERROR = "Authentication authCode error.";
	private static final String EXCEP_KEY = "SPRING_SECURITY_LAST_EXCEPTION";

	@Inject
	private EmployeeService employeeServiceImpl;

	@Inject
	private BCryptPasswordEncoder bcryptPasswordEncoder;

	@Inject
	private EmployeeGroupService employeeGroupServiceImpl;

	@Inject
	private SecurityUserCache securityUserCache;

	/**
	 * 执行实际的新增操作
	 * 
	 * @param model
	 *            要新增的数据
	 * @return 新增页面逻辑视图
	 */
	@ResponseBody
	@RequestMapping("/doAdd")
	public JsonBean doAdd(@Valid Employee model, BindingResult errors,HttpServletResponse response) {
		JsonBean bean = new JsonBean();
		response.setHeader("X-Frame-Options", "SAMEORIGIN");
		try {
			if (errors.hasErrors()) {
				bean.setMessage("参数错误。");
				return bean;
			}
			int ret = saveFile(model);
			if (ret == 0) {
				bean.setMessage("头像文件不能大于2M！");
				return bean;
			}
			model.setCreateTime(new Date());
			int result = employeeServiceImpl.saveEmployee(model);
			if (result == 1) {
				bean.setMessage("添加用户成功！"); // 成功
				bean.setCode(1);
				LOGGER.info("save record success.");
			} else if (result == 3) {
				bean.setCode(0);
				bean.setMessage("添加用户失败，没有该部门");
			} else {
				bean.setCode(0);
				bean.setMessage("添加用户失败");
				LOGGER.error("save record error.");
			}
			getHttpServletResponse().setHeader("X-Frame-Options", "SAMEORIGIN");
		} catch (Exception e) {
			bean.setCode(0);
			bean.setMessage("添加用户失败");
			LOGGER.error("save record error, errorMsg=[{}].", e.getMessage());
		}
		return bean;
	}

	/**
	 * 保存图片
	 * 
	 * @param model
	 *            含file参数
	 * @return 0文件太大，1成功，2文件内容为空
	 * @throws IOException
	 */
	private int saveFile(Employee model) throws IOException {
		int result = 0;
		MultipartFile multipartFile = model.getFile();
		if (multipartFile != null && multipartFile.getSize() > 0) {
			// spring mvc已经配置了，这里再次控制一下
			if (multipartFile.getSize() > (1024 * 1024 * 2L)) { // 2M
				return result; // 文件太大
			}
			model.setAvatar(MyFileUtils.uploadImg(multipartFile, ImgType.AVATAR));
			result = 1;
		} else {
			result = 2; // 文件内容为空
		}
		return result;
	}

	/**
	 * 验证文件是否存在，如果存在设置文件保存的路径等
	 * 
	 * @param model
	 *            含file参数
	 * @param type
	 *            1新增，2更新
	 * @return 1成功，0文件太大，2文件内容为空，3文件格式不正确
	 */
	@SuppressWarnings("unused")
	private int checkFile(Employee model, int type) {
		MultipartFile multipartFile = model.getFile();
		if (multipartFile != null && multipartFile.getSize() > 0) {
			// spring mvc已经配置了，这里再次控制一下
			if (multipartFile.getSize() > (1024 * 1024 * 1024 * 2L)) { // 2M
				return 0; // 文件太大
			}
			String fileName = multipartFile.getOriginalFilename().toLowerCase();
			// 正则判断图片
			if (IMAGE.matcher(fileName).matches()) {
				String fileExt = fileName.substring(fileName.lastIndexOf(".")); // 带点
				// 这个是网络访问的路径
				String avatar = PropUtils.get("avatar.path", "avatar/") + model.getAccount()
						+ fileExt;
				model.setAvatar(avatar);

				// 这个是实际的文件路径
				String realPath = getHttpServletRequest().getServletContext().getRealPath("/");
				realPath = realPath + "/" + avatar;
				model.setFilePath(realPath);
			} else {
				return 3; // 文件格式不正确
			}
		} else {
			if (type == 1) {
				return 2; // 文件内容为空
			} else if (type == 2) { // 更新的情况下，文件为空，不管
				model.setFile(null); // 没有文件内容，清空
			}
		}
		return 1;
	}

	/**
	 * 查看员工详情页。
	 * 
	 * @param userId
	 *            用户ID
	 * @return 员工详情
	 */
	@ResponseBody
	@RequestMapping("/detail/{userId}")
	public EmployeeDetailResBean detail(@PathVariable("userId") String userId) {

		EmployeeDetailResBean model = null;
		if (StringUtils.isBlank(userId)) {
			LOGGER.error("params userId cannot be null.");
			return model;
		}
		try {
			model = employeeServiceImpl.getEmployeeDetailResBean(userId);
			model.setLoginPwd(null);
			model.setWorkPwd(null);
			DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
			if (null != model.getEntryTime()) {
				model.setEntryTimeStr(df.format(model.getEntryTime()));
			}
			if (null != model.getBirthday()) {
				model.setBirthdayStr(df.format(model.getBirthday()));
			}
		} catch (Exception e) {
			LOGGER.error("detail user, get user error, userId=[{}], msg=[{}].", userId,
					e.getMessage());
		}
		return model;
	}

	/**
	 * 更新员工信息，
	 * 
	 * @param model
	 *            要更新的员工信息，含有ID
	 * @return 操作结果信息
	 */
	@ResponseBody
	@RequestMapping("/update")
	public JsonBean update(Employee model) {
		JsonBean bean = new JsonBean();
		if (StringUtils.isBlank(model.getEmployeeId())) {
			bean.setMessage("update Employee, employeeId cannot be null.");
			return bean;
		}
		try {
			int ret = saveFile(model);
			if (ret == 0) {
				bean.setMessage("头像文件不能大于2M！");
				return bean;
			}
			int result = employeeServiceImpl.updateEmployee(model);
			if (result == 1) {
				bean.setMessage("员工修改成功！");
				bean.setCode(1);
				LOGGER.info("update record success.");
			} else {
				bean.setMessage("修改员工出错！");
				bean.setCode(0);
				LOGGER.error("update record error.");
			}
			getHttpServletResponse().setHeader("X-Frame-Options", "SAMEORIGIN");
		} catch (Exception e) {
			LOGGER.error("update record error, errorMsg=[{}].", e.getMessage());
			bean.setMessage("修改员工出现异常！");
			bean.setCode(0);
		}
		return bean;
	}

	/**
	 * 更新员工单个的一些信息，密码和解除设备绑定
	 * 
	 * @param model
	 *            要更新的员工信息，含有ID
	 * @return 操作结果信息
	 */
	@ResponseBody
	@RequestMapping("/updateEmpPassword")
	public JsonBean updateEmpPassword(@RequestBody Employee model) {
		JsonBean bean = new JsonBean();

		String employeeId = model.getEmployeeId();
		if (StringUtils.isBlank(employeeId)) {
			bean.setMessage("Update Employee, Params is required.");
			return bean;
		}

		Integer state = model.getState();
		if (state == null) {
			bean.setMessage("Update Employee, state is required.");
			return bean;
		}

		try {
			if (state == 3) {
				Employee employee = employeeServiceImpl.get(employeeId);
				String loginPwd = UUIDUtils.id(6).toString();
				String reString = SmsUtils.send(employee.getMobile(), "您的登录密码已被重置为"+ loginPwd);
				if (reString.contains("true")) {
					employee.setLoginPwd(bcryptPasswordEncoder.encode(loginPwd));
					employeeServiceImpl.updateById(employee);
					bean.setCode(3);
					bean.setMessage("登录密码重置成功");
					if (LOGGER.isInfoEnabled()) {
						LOGGER.info("登录密码重置成功");
					}
				} else {
					bean.setCode(4);
					bean.setMessage("登录密码重置失败");
					if (LOGGER.isInfoEnabled()) {
						LOGGER.info("登录密码重置失败");
					}
				}
				return bean;
			}
			String workPwd = model.getWorkPwd();
			String loginPwd = model.getLoginPwd();
			if (StringUtils.isAnyBlank(workPwd, loginPwd)) {
				bean.setMessage("新密码不能为空！");
				return bean;
			}
			// 两个值要相等
			if (!workPwd.equals(loginPwd)) {
				bean.setMessage("两次输入密码不相等！");
				return bean;
			}
			// 因为两个值相等，下面统一使用workPwd
			if (workPwd.length() < 6 || workPwd.length() > 20) {
				bean.setMessage("密码设置不正确。");
				return bean;
			}
			workPwd = bcryptPasswordEncoder.encode(workPwd);

			if (state == 2) { // 修改工作密码
				model.setWorkPwd(workPwd);
				model.setLoginPwd(null);
			} else if (state == 3) { // 修改登录密码
				model.setLoginPwd(workPwd);
				model.setWorkPwd(null);
			}

			int result = employeeServiceImpl.updateInfo(model);
			if (result == 1) {
				bean.setMessage("员工修改成功！");
				bean.setCode(1);
				LOGGER.info("update record success.");
			} else {
				bean.setMessage("修改员工出错！");
				LOGGER.error("update record error.");
			}

		} catch (Exception e) {
			LOGGER.error("update record error, errorMsg=[{}].", e.getMessage());
			bean.setMessage("修改员工出现异常！");
		}
		return bean;
	}

	/**
	 * 修改当前用户的密码
	 * 
	 * @param model
	 *            要更新的员工信息，含有ID
	 * @return 操作结果信息
	 */
	@ResponseBody
	@RequestMapping("/updatePassword")
	public JsonBean updatePassword(HttpServletRequest request,
			@RequestBody UserPasswordReqBean model) {
		JsonBean bean = new JsonBean();
		try {
			if (StringUtils.isAnyBlank(model.getUserOldpasswd(), model.getUserNewpasswd())) {
				bean.setCode(0);
				bean.setMessage("参数不能为空");
				return bean;
			}
			if (model.getUserNewpasswd().length() < 6 || model.getUserNewpasswd().length() > 20) {
				bean.setCode(0);
				bean.setMessage("密码设置不正确。");
				return bean;
			}

			Employee user = employeeServiceImpl.get(UserUtils.getUserId());
			if (user == null) {
				bean.setCode(0);
				bean.setMessage("请先登录");
				return bean;
			}
			if (model.getUserState() == 1) {// 修改登录密码
				if (bcryptPasswordEncoder.matches(model.getUserOldpasswd(), user.getLoginPwd())) {
					Employee employee = new Employee();
					employee.setEmployeeId(UserUtils.getUserId());
					employee.setLoginPwd(bcryptPasswordEncoder.encode(model.getUserNewpasswd()));
					int result = employeeServiceImpl.updateById(employee);
					if (result > 0) {
						logout(request);// 清除缓存
						bean.setCode(2);
						bean.setMessage(SUCCESS);
					} else {
						bean.setCode(0);
						bean.setMessage("修改密码失败，请稍后重试");
					}
				} else {
					bean.setCode(0);
					bean.setMessage("旧密码错误");
				}
			} else if (model.getUserState() == 2) {// 修改工作密码
				if (bcryptPasswordEncoder.matches(model.getUserOldpasswd(), user.getWorkPwd())) {
					Employee employee = new Employee();
					employee.setEmployeeId(UserUtils.getUserId());
					employee.setWorkPwd(bcryptPasswordEncoder.encode(model.getUserNewpasswd()));
					int result = employeeServiceImpl.updateById(employee);
					if (result > 0) {
						bean.setCode(1);
						bean.setMessage(SUCCESS);
					} else {
						bean.setCode(0);
						bean.setMessage("修改密码失败，请稍后重试");
					}
				} else {
					bean.setCode(0);
					bean.setMessage("旧密码错误");
				}
			} else {
				bean.setCode(0);
				bean.setMessage("请选择一个你要修改的密码");
			}
		} catch (Exception e) {
			LOGGER.error("employee updatePassword error, msg=[{}]", e.getMessage());
			bean.setCode(0);
			bean.setMessage(ERROR);
			return bean;
		}
		return bean;
	}

	public void logout(HttpServletRequest request) {
		HttpSession session = request.getSession(false);
		if (session != null) {
			LOGGER.debug("Invalidating session: " + session.getId());
			session.invalidate();
		}

		Authentication au = SecurityContextHolder.getContext().getAuthentication();
		if (au != null) {
			IUserDetails user = (IUserDetails) au.getPrincipal();
			if (user != null) {
				securityUserCache.removeUserFromCache(user.getAccount(), user.getTenantCode());
			}
		}

		SecurityContext context = SecurityContextHolder.getContext();
		context.setAuthentication(null);

		SecurityContextHolder.clearContext();
	}

	@RequestMapping("/login")
	public String login(String authError) {
		// 区分是验证码错误的异常
		Exception exception = (Exception) getHttpSession().getAttribute(EXCEP_KEY);
		if (exception != null) {
			String msg = exception.getMessage();
			if (AUTH_ERROR.equals(msg)) {
				if (LOGGER.isInfoEnabled()) {
					LOGGER.info("auth code error.");
				}
				setAttributeToRequest("authCodeError", true);
			}
		}
		return "login";
	}

	/**
	 * 控制弹出框，login是form提交的
	 * 
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping("/clean")
	public boolean clean() {
		getHttpSession().removeAttribute(EXCEP_KEY);
		return true;
	}

	/**
	 * 对数据进行验证
	 * 
	 * @param model
	 *            待验证的参数
	 * @param errors
	 *            验证结果
	 * @return true成功，false失败
	 */
	@ResponseBody
	@RequestMapping("/check")
	public boolean check(Employee model, Integer type) {
		if (type == null) {
			return false;
		}
		if (type == 4) { // 身份证，先验证正则
			if (model.getIdcard() == null || !ID.matcher(model.getIdcard()).matches()) {
				return false;
			}
		} else if (type == 3) { // 手机号的正则
			if (model.getMobile() == null || !MOBILE.matcher(model.getMobile()).matches()) {
				return false;
			}
		}
		model.setOrgId(UserUtils.getOrgId());
		// 不为空，是修改
		String employeeId = model.getEmployeeId();
		if (StringUtils.isNotBlank(employeeId)) {
			Employee employee = employeeServiceImpl.get(employeeId);
			if (employee == null) {
				return false;
			}
			int result = employeeServiceImpl.countBy(model);
			if (result > 1) {
				return false;
			} else if (result == 1) { // 存在重复，且不是自己的，不允许
				if (type == 3) {
					if (!model.getMobile().equals(employee.getMobile())) {
						return false;
					}
				} else if (type == 4) {
					if (!model.getIdcard().equals(employee.getIdcard())) {
						return false;
					}
				} else if (type == 1) {
					if (!model.getAccount().equals(employee.getAccount())) {
						return false;
					}
				} else if (type == 2) {
					if (!model.getEmployeeNo().equals(employee.getEmployeeNo())) {
						return false;
					}
				}
			}
		} else {
			// 该机构是否存在相同的
			// 账户、工号、手机号、身份证，验证唯一性，可以使用相同的验证方式
			int result = employeeServiceImpl.countBy(model);
			// 已经存在了
			if (result >= 1) {
				return false;
			}
		}
		return true;
	}

	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		// 空字符串转换为null
		binder.registerCustomEditor(String.class, new StringEditor());
		binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(
				"yyyy-MM-dd"), true));
	}

	/**
	 * 员工离职
	 * 
	 * @param id
	 * @return
	 */
	@ResponseBody
	@RequestMapping("/leave/{id}")
	public JsonBean leave(@PathVariable String id) {
		JsonBean json = new JsonBean();
		if (StringUtils.isBlank(id)) {
			LOGGER.error("params userId cannot be null.");
			json.setCode(0);
			json.setMessage(ERROR);
			return json;
		}
		try {
			Employee employee = employeeServiceImpl.get(id);
			if (null == employee) {
				json.setCode(0);
				json.setMessage("员工不存在！");
				return json;
			}
			int result = employeeServiceImpl.leave(employee);
			if (result == 1) {
				json.setCode(1);
				json.setMessage(SUCCESS);
			} else {
				json.setCode(0);
				json.setMessage("离职失败！");
			}
		} catch (Exception e) {
			LOGGER.error("leave employee error, id=[{}], msg=[{}].", id, e.getMessage());
			json.setCode(0);
			json.setMessage(ERROR);
		}
		return json;
	}

	/**
	 * 设为队长
	 * 
	 * @param id
	 * @return
	 */
	@ResponseBody
	@RequestMapping("/setLeader/{id}")
	public JsonBean setLeader(@PathVariable String id) {
		JsonBean json = new JsonBean();
		if (StringUtils.isBlank(id)) {
			LOGGER.error("params userId cannot be null.");
			json.setCode(0);
			json.setMessage(ERROR);
			return json;
		}
		try {
			Employee employee = employeeServiceImpl.get(id);
			if (null == employee) {
				json.setCode(0);
				json.setMessage(ERROR);
				return json;
			}
			EmployeeGroup employeeGroup = employeeGroupServiceImpl.get(employee.getDeptId());
			if (null == employeeGroup) {
				json.setCode(0);
				json.setMessage(ERROR);
				return json;
			}
			EmployeeGroup updataEmployeeGroup = new EmployeeGroup();
			updataEmployeeGroup.setId(employee.getDeptId());
			updataEmployeeGroup.setEmployeeId(employee.getId());
			updataEmployeeGroup.setEmployeeName(employee.getName());
			int result = employeeGroupServiceImpl.updateById(updataEmployeeGroup);
			if (result == 1) {
				json.setCode(1);
				json.setMessage(SUCCESS);
			} else {
				json.setCode(0);
				json.setMessage("设置队长失败，请稍后重试！");
			}
		} catch (Exception e) {
			LOGGER.error("leave employee error, id=[{}], msg=[{}].", id, e.getMessage());
			json.setCode(0);
			json.setMessage(ERROR);
		}
		return json;
	}
}
